package model

import (
	myConfig "common/config"
	"common/helper"
	myRedis "common/redis"
	"common/userHelp"
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
	"github.com/jmoiron/sqlx"
	"time"
)

/*
定时器
*/

func StartTimer() {
	m_iLastHour = -1
	for {
		iCurWeek := int(time.Now().Weekday())
		iCurHour := time.Now().Hour()
		iCurMinute := time.Now().Minute()
		iCurSeconds := time.Now().Second()

		//接近0点 实时处理统计数据 这样数据就不会统计到第二天
		if iCurHour == 23 && iCurMinute == 59 && iCurSeconds >= 50 {
			UpdateStatisticsData(context.Background(), GetRedisInstance(), GetMasterDBInstance())
		}

		CalcProxyCommWeekReturn(iCurWeek, iCurHour)
		CalcDepositWeekReturn(iCurWeek, iCurHour)
		CalcBetWeekReturn(iCurWeek, iCurHour)
		CalcLostWeekReturn(iCurWeek, iCurHour)
		CalcBetDailyReturn(iCurWeek, iCurHour)
		CalcProxyChildWagedReturn(iCurWeek, iCurHour)
		LotterySpin(iCurWeek, iCurHour)

		m_iLastHour = time.Now().Hour()
		time.Sleep(1000 * time.Millisecond) // 等待时间间隔后重试
	}
}

/*
周返利计算
*/
var m_iLastHour int = -1

func CalcProxyCommWeekReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_WeekCcommi) == 0 {
		return
	}

	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgProxyCommWeekReturnCalcHour) % 24
	nWeekDay := myConfig.GetGameCfgInt(myConfig.CfgWeekReturnCalcDay) % 7

	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 && iCurWeek == nWeekDay {
		helper.GetloggerInstance().Info("CalcProxyCommWeekReturn")
		_, errExec := GetMasterDBInstance().Exec("CALL calc_user_week(?)", 1)
		if errExec != nil {
			helper.GetloggerInstance().Emergencyf("CALL calc_user_week(1);	%s", errExec.Error())
		}
	}
}

func CalcDepositWeekReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_WeekDeposit) == 0 {
		return
	}

	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgDepositWeekReturnCalcHour) % 24
	nWeekDay := myConfig.GetGameCfgInt(myConfig.CfgWeekReturnCalcDay) % 7
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 && iCurWeek == nWeekDay {
		helper.GetloggerInstance().Info("CalcDepositWeekReturn")
		_, errExec := GetMasterDBInstance().Exec("CALL calc_user_week(?)", 2)
		if errExec != nil {
			helper.GetloggerInstance().Emergencyf("CALL calc_user_week(2);	%s", errExec.Error())
		}
	}
}

type ProxyChildWaged struct {
	UID        int     `json:"UID" db:"uid" cbor:"UID"`
	Level      int     `json:"Level" db:"level" cbor:"Level"`
	ValidWaged float64 `json:"ValidWaged" db:"valid_waged" cbor:"ValidWaged"`
}

func CalcProxyChildWagedReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_ProxyChildRunningReturn) == 0 {
		return
	}
	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgChildWagedReturnCalcHour) % 24
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 {
		yesTerday := time.Now().AddDate(0, 0, -1)
		SqlSelect := fmt.Sprintf("SELECT uid,level,valid_waged FROM `tbl_report_proxy_daily` WHERE created_at='%s' AND valid_waged>0 ", yesTerday.Format("2006-01-02"))
		helper.InfoLog(SqlSelect)

		var selectItem []ProxyChildWaged
		err := GetMasterDBInstance().Select(&selectItem, SqlSelect)

		if err != nil {
			helper.SqlSelectErrLog("CalcProxyChildWagedReturn:%s---%s", SqlSelect, err.Error())
			return
		}

		for index := 0; index < len(selectItem); index++ {
			var ChildWagedReturn float64 = 0.00
			var SqlUpdate string
			if selectItem[index].Level == 1 {
				ChildWagedReturn = selectItem[index].ValidWaged * myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelOneRate) / 100
				SqlUpdate = fmt.Sprintf("update tbl_member_return set ChildWagedReturnLevelOne = ChildWagedReturnLevelOne + %0.2f where uid=%d", ChildWagedReturn, selectItem[index].UID)
			} else if selectItem[index].Level == 2 {
				ChildWagedReturn = selectItem[index].ValidWaged * myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelTwoRate) / 100
				SqlUpdate = fmt.Sprintf("update tbl_member_return set ChildWagedReturnLevelTwo = ChildWagedReturnLevelTwo + %0.2f where uid=%d", ChildWagedReturn, selectItem[index].UID)
			} else if selectItem[index].Level == 3 {
				ChildWagedReturn = selectItem[index].ValidWaged * myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelThreeRate) / 100
				SqlUpdate = fmt.Sprintf("update tbl_member_return set ChildWagedReturnLevelThree = ChildWagedReturnLevelThree + %0.2f where uid=%d", ChildWagedReturn, selectItem[index].UID)
			}

			if ChildWagedReturn > 0.00 {
				helper.GetloggerInstance().Infof("CalcProxyChildWagedReturn:%s", SqlUpdate)
				GetMasterDBInstance().Exec(SqlUpdate)
			}
		}
		ProxyChildWagedReturnRecord()
	}
}

type ProxyChildWagedDetail struct {
	Uid            int     `json:"uid" db:"uid" cbor:"uid"`
	Parent_id      int     `json:"parent_id" db:"parent_id" cbor:"parent_id"`
	Grand_id       int     `json:"grand_id" db:"grand_id" cbor:"grand_id"`
	Great_grand_id int     `json:"great_grand_id" db:"great_grand_id" cbor:"great_grand_id"`
	ValidWaged     float64 `json:"valid_waged" db:"valid_waged" cbor:"valid_waged"`
}

func ProxyChildWagedReturnRecord() {
	Yesterday := time.Now().AddDate(0, 0, -1)
	strYesterday := Yesterday.Format("2006-01-02")
	SqlSelect := fmt.Sprintf("SELECT b.uid,b.parent_id,b.grand_id,b.great_grand_id,a.valid_waged FROM tbl_report_user_daily AS a"+
		"	LEFT JOIN   tbl_proxy_base AS b"+
		"	on a.uid = b.uid"+
		"	where a.created_at='%s' and a.valid_waged > 0 and (b.parent_id > 0)"+
		"	order by b.uid ", strYesterday)
	helper.InfoLog(SqlSelect)

	LevelOneRate := myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelOneRate)
	LevelTwoRate := myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelTwoRate)
	LevelThreeRate := myConfig.GetGameCfgFloat64(myConfig.CfgChildWagedReturnLevelThreeRate)
	var selectItem []ProxyChildWagedDetail
	GetMasterDBInstance().Select(&selectItem, SqlSelect)
	for index := 0; index < len(selectItem); index++ {
		var ChildWagedReturn float64 = 0.00
		var SqlUpdate string
		if selectItem[index].Parent_id > 0 && LevelOneRate > 0.0 {
			ChildWagedReturn = selectItem[index].ValidWaged * LevelOneRate / 100
			SqlUpdate = fmt.Sprintf("INSERT INTO tbl_record_proxy_waged_return(uid,created_at,superior_id,level,valid_waged,return_rate,waged_commi) VALUES "+
				"(%d,'%s',%d,%d,%0.2f,%0.2f,%0.5f)",
				selectItem[index].Uid, strYesterday, selectItem[index].Parent_id, 1, selectItem[index].ValidWaged, LevelOneRate, ChildWagedReturn)
			myRedis.AddLogToRedis(SqlUpdate)
		}

		if selectItem[index].Grand_id > 0 && LevelTwoRate > 0.0 {
			ChildWagedReturn = selectItem[index].ValidWaged * LevelTwoRate / 100
			SqlUpdate = fmt.Sprintf("INSERT INTO tbl_record_proxy_waged_return(uid,created_at,superior_id,level,valid_waged,return_rate,waged_commi) VALUES "+
				"(%d,'%s',%d,%d,%0.2f,%0.2f,%0.5f)",
				selectItem[index].Uid, strYesterday, selectItem[index].Grand_id, 2, selectItem[index].ValidWaged, LevelTwoRate, ChildWagedReturn)
			myRedis.AddLogToRedis(SqlUpdate)
		}

		if selectItem[index].Great_grand_id > 0 && LevelThreeRate > 0.0 {
			ChildWagedReturn = selectItem[index].ValidWaged * LevelThreeRate / 100
			SqlUpdate = fmt.Sprintf("INSERT INTO tbl_record_proxy_waged_return(uid,created_at,superior_id,level,valid_waged,return_rate,waged_commi) VALUES "+
				"(%d,'%s',%d,%d,%0.2f,%0.2f,%0.5f)",
				selectItem[index].Uid, strYesterday, selectItem[index].Great_grand_id, 3, selectItem[index].ValidWaged, LevelThreeRate, ChildWagedReturn)
			myRedis.AddLogToRedis(SqlUpdate)
		}
	}
}
func CalcBetDailyReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_DailyBet) == 0 {
		return
	}
	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgBetDailyReturnCalcHour) % 24
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 {
		helper.GetloggerInstance().Info("CalcBetDailyReturn")
		_, errExec := GetMasterDBInstance().Exec("CALL calc_user_week(?)", 5)
		if errExec != nil {
			helper.GetloggerInstance().Emergencyf("CALL calc_user_week(5);	%s", errExec.Error())
		}
	}
}

func CalcBetWeekReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_WeekBet) == 0 {
		return
	}

	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgBetWeekReturnCalcHour) % 24
	nWeekDay := myConfig.GetGameCfgInt(myConfig.CfgWeekReturnCalcDay) % 7
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 && iCurWeek == nWeekDay {
		helper.GetloggerInstance().Info("CalcBetWeekReturn")
		_, errExec := GetMasterDBInstance().Exec("CALL calc_user_week(?)", 3)
		if errExec != nil {
			helper.GetloggerInstance().Emergencyf("CALL calc_user_week(3);	%s", errExec.Error())
		}
	}
}

func CalcLostWeekReturn(iCurWeek int, iCurHour int) {
	if myConfig.IsActiveOpen(myConfig.ActiveType_WeekLost) == 0 {
		return
	}
	nCalcHour := myConfig.GetGameCfgInt(myConfig.CfgLostWeekReturnCalcHour) % 24
	nWeekDay := myConfig.GetGameCfgInt(myConfig.CfgWeekReturnCalcDay) % 7
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 && iCurWeek == nWeekDay {
		helper.GetloggerInstance().Info("CalcLostWeekReturn")
		_, errExec := GetMasterDBInstance().Exec("CALL calc_user_week(?)", 4)
		if errExec != nil {
			helper.GetloggerInstance().Emergencyf("CALL calc_user_week(4);	%s", errExec.Error())
		}
	}
}

func UpdateStatisticsData(ctx context.Context, redis *redis.Client, sqlCon *sqlx.DB) {
	if redis == nil || sqlCon == nil {
		return
	}

	members, err := redis.SMembers(context.Background(), "UpdateRoleSet").Result()
	if err != nil {
		return
	}

	// 输出集合中的所有成员
	for _, valUid := range members {
		dataFieldLock := fmt.Sprintf("%s", valUid)
		myRedis.Lock(GetRedisInstance(), dataFieldLock)
		UpdateProxyStatisticsData(ctx, redis, sqlCon, valUid)
		myRedis.Unlock(GetRedisInstance(), dataFieldLock)
	}
}
func LotterySpin(iCurWeek int, iCurHour int) {
	nCalcHour := myConfig.G_LotteryCfg.OpenHour
	if iCurHour == nCalcHour && iCurHour != m_iLastHour && m_iLastHour != -1 {
		userHelp.AutoLottery()
		userHelp.ResetLottery()
	}
}
